﻿using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Text;
using System.Collections.Generic;

namespace NS_MyUdpServer
{
    public class MyUdpServer
    {
        private UdpClient UDPServer=null;
        private Thread thrSocket;
        private bool bRunning = false;
        private StringBuilder sbRecvBuffer;

        private int udpPortLocal = 5100;
        private int udpPortRemote = 6100;

        private IPEndPoint remoteIpep = new IPEndPoint(IPAddress.Any, 0);
        private ReaderWriterLock rwLock = new ReaderWriterLock();
        public static Queue<string> listRecv = new Queue<string>();//收到的消息队列
        private string buf="";

        public delegate void LogHandle(string e);
        public LogHandle UE_LogHandle;

        public MyUdpServer()
        {
        }

        public void Start()
        {
            try
            {
                sbRecvBuffer = new StringBuilder();
                IPEndPoint ip = new IPEndPoint(IPAddress.Any, udpPortLocal);
                UDPServer = new UdpClient(ip);
                thrSocket = new Thread(ThreadSocket);
                bRunning = true;
                thrSocket.Start();
            }
            catch (Exception ex)
            {
                Console.Out.WriteLine(ex.Message + "\n" + ex.StackTrace);
                if (UE_LogHandle != null)
                    UE_LogHandle("启动UDP Server 错误：\n" + ex.Message + "\n" + ex.StackTrace);
            }
        }

        public void Stop()
        {
            bRunning = false;
        }

        /// <summary>
        /// 数据收发线程
        /// </summary>
        /// <param name="obj"></param>
        private void ThreadSocket(object obj)
        {
            if (UE_LogHandle != null)
                UE_LogHandle("启动UDP Server");
      
            while (bRunning)
            {
                try
                {
                    if (UDPServer.Available > 0)
                    {
                        byte[] byteRecv = UDPServer.Receive(ref remoteIpep);
                        string message = Encoding.GetEncoding("UTF-8").GetString(
                            byteRecv, 0, byteRecv.Length);
                        //Console.Out.WriteLine(string.Format("{0}--{1}", remoteIpep, message));
                        if (UE_LogHandle != null)
                            UE_LogHandle(string.Format("UDP收到：{0}--{1}", remoteIpep, message));

                        //处理消息
                        string rs=ProcessUdpMsg(message);
                        

                        //自动回应消息
                        if (rs.Length > 0 && !rs.StartsWith("*[;2401;"))
                        {
                            byte[] bs = Encoding.GetEncoding("UTF-8").GetBytes(rs);
                            remoteIpep.Port = udpPortRemote;
                            UDPServer.Send(bs, bs.Length, remoteIpep);
                            if (UE_LogHandle != null)
                                UE_LogHandle(string.Format("UDP发送：{0}--{1}", remoteIpep, rs));

                            //Console.Out.WriteLine("UDP发送：" + rs);
                        }
                    }
                    else
                        Thread.Sleep(100);
                }
                catch (Exception ex)
                {
                    Console.Out.WriteLine(ex.Message + "\n" + ex.StackTrace);
                    break;
                }
            }
            close();
            Console.Out.WriteLine("Udp receive thread exit.");
        }

        public bool IsRunning
        {
            // self-explanitory
            get { return bRunning; }
        }

        public void close()
        {
            try
            {
                bRunning = false;
                if (UDPServer != null)
                    UDPServer.Close();
            }
            catch (Exception ex)
            {
                Console.Out.WriteLine(ex.Message);
            }
        }

        /// <summary>
        /// 处理收到的消息，并生成响应消息
        /// </summary>
        /// <param name="msg">收到的消息</param>
        /// <returns>响应消息，如果长度为0表示消息不完整，不响应</returns>
        private string ProcessUdpMsg(string msg)
        {
            buf += msg;
            int b = -1;
            int e = -1;
            b = buf.IndexOf("*[;");
            e = buf.IndexOf(";]");
            if (b >= 0 && e > 0)
            {
                string s = buf.Substring(b, e - b + 2);
                listRecv.Enqueue(s);
                buf = buf.Substring(e + 2);
                string[] sl=s.Split(';');
                if (!sl[1].EndsWith("1")) //如果本条命令不是应答命令，就生成应答命令
                {
                    string rs = sl[0] + ";" + sl[1].Substring(0, 3) + "1;" + sl[2] + ";" + "OK;;]";
                    return rs;
                }
            }

            return "";
        }

        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="msg"></param>
        /// <returns>大于0成功；小于等于0失败</returns>
        public int SendMsg(string msg,string remoteIp="",int remotePort=6100)
        {
            int rtn = 0;
            try
            {
                if (msg.Length > 0)
                {
                    byte[] bs = Encoding.GetEncoding("UTF-8").GetBytes(msg);
                    if (remotePort == 0)
                        remoteIpep.Port = udpPortRemote;
                    else
                        remoteIpep.Port = remotePort;

                    if (remoteIp.Length > 0)
                        remoteIpep.Address = IPAddress.Parse(remoteIp);

                    rtn = UDPServer.Send(bs, bs.Length, remoteIpep);
                    if (UE_LogHandle != null)
                        UE_LogHandle(string.Format("UDP发送：{0}--{1}", remoteIpep, msg));

                    //Console.Out.WriteLine("UDP发送：" + rs);
                }

            }
            catch (Exception ex)
            {
                Console.Out.WriteLine(ex.Message + "\n" + ex.StackTrace);
            }
            return rtn;
        }
    }
}
